package com.grape.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.grape.constants.Constants;
import com.grape.error.BusinessException;
import com.grape.utils.StringUtils;
import com.grape.vo.BaseVo;
import com.grape.vo.RoleMenuVO;
import com.grape.vo.RolePermissionVO;
import com.grape.wrapper.BaseWrapper;
import com.grape.entity.SysRole;
import com.grape.entity.SysUser;
import com.grape.domain.SysUserRole;
import com.grape.mapper.SysRoleMapper;
import com.grape.mapper.SysUserMapper;
import com.grape.service.*;
import lombok.AllArgsConstructor;
import org.apache.logging.log4j.util.Strings;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 *
 * 角色信息表 服务实现类
 *
 * @author  putao
 * @email   2628279194@qq.com
 */
@Service
@AllArgsConstructor
@Transactional(readOnly = true)
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements ISysRoleService {

    private final SysRoleMapper sysRoleMapper;

    private final ISysRolePermissionService rolePermissionService;

    private final ISysRoleMenuService roleMenuService;

    private final ISysUserRoleService userRoleService;

    private final SysUserMapper userMapper;

    private final ISysPermissionService permissionService;

    /**
     * 分页
     * @param baseVo 统一分页对象
     * @return 角色信息表集合
     */
    @Override
    public List<SysRole> listData(BaseVo baseVo) {
        QueryWrapper<SysRole> wrapper = new BaseWrapper<SysRole>().init();
        wrapper.like(Strings.isNotBlank(baseVo.getSearch()), "name", baseVo.getSearch())
                .eq(StringUtils.isNotBlank(baseVo.getColumnName())
                && StringUtils.isNotBlank(baseVo.getSelect()), baseVo.getColumnName(), baseVo.getSelect())
                .orderByAsc("role_sort");
        return this.list(wrapper);
    }

    /**
     * 修改
     * @param sysRole 角色信息表对象
     */
    @Override
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    public void updateData(SysRole sysRole) {
        this.baseUpdate(sysRole);
    }

    /**
     * 新增
     * @param sysRole 角色信息表对象
     * @return 角色信息表对象
     */
    @Override
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    public SysRole insertData(SysRole sysRole) {
        if (!sysRole.getRoleKey().contains("ROLE_")) {
            throw new BusinessException("角色权限字符必须以ROLE_开头");
        }
        this.checkIsRepeat(null, sysRole, "role_key", MessageFormat.format("角色权限字符：{0} 已存在", sysRole.getRoleKey()));
        sysRole.setStatus(Constants.ZERO_STR);
        return this.baseInsert(sysRole);
    }

    /**
     * 删除
     * @param id    单据id
     * @return      删除条数
     */
    @Override
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    public int deleteData(String id) {
        return this.baseDelete(id);
    }

    /**
     * 根据id查询详情
     * @param id    角色ID
     * @return      角色信息表对象
     */
    @Override
    public SysRole detail(String id) {
        return this.getById(id);
    }

    /**
     * 根据用户id查询角色列表
     * @param userId    用户id
     * @return          角色集合
     */
    @Override
    public List<SysRole> getRoleByUserId(String userId) {
        return sysRoleMapper.getRoleByUserId(userId);
    }

    /**
     * 根据用户id查询角色列表
     * @param userIdList    用户id集合
     * @return              角色集合
     */
    @Override
    public List<SysRole> getRoleByUserIdList(List<String> userIdList) {
        return sysRoleMapper.getRoleByUserIdList(userIdList);
    }

    /**
     * 修改角色的权限
     * @param rolePermissionVo  角色和权限数据
     */
    @Override
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    public void updateRolePermissionList(RolePermissionVO rolePermissionVo) {
        rolePermissionService.updateRolePermissionList(rolePermissionVo);
        List<SysUser> userList = userMapper.selectUserListByRoleId(rolePermissionVo.getRoleId());
        if (CollectionUtil.isEmpty(userList)) {
            return;
        }
        permissionService.refreshPermissionByUserIdList(userList.stream().map(SysUser::getId).collect(Collectors.toList()));
    }

    /**
     * 修改菜单的权限
     * @param roleMenuVo  角色和菜单数据
     */
    @Override
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    public void updateRoleMenuList(RoleMenuVO roleMenuVo) {
        roleMenuService.updateRoleMenuList(roleMenuVo);
    }

    /**
     * 查询全部话题（未删除，且审核状态为审核通过的）
     * @return  角色信息表集合
     */
    @Override
    public List<SysRole> listAll() {
        return sysRoleMapper.selectList(new QueryWrapper<SysRole>().eq(Constants.DEL_FLAG, Constants.ZERO_STR));
    }

    /**
     * 根据角色编码给用户默认权限
     * @param sysUser   用户
     * @param roleCode  默认权限编码（多个时,拼接）
     */
    @Override
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    public void addDefaultRoleForUser(SysUser sysUser, String roleCode) {
        if (StringUtils.isBlank(roleCode)) {
            throw new BusinessException("赋值默认权限失败: 默认角色编码为空");
        }
        List<SysRole> roleList = this.list(new QueryWrapper<SysRole>().in("code", StringUtils.convertList(roleCode)));
        if (CollectionUtil.isEmpty(roleList)) {
            throw new BusinessException(MessageFormat.format("赋值默认权限失败: 根据默认角色编码：{0}，无法查询角色信息，赋值权限失败", roleCode));
        }
        List<SysUserRole> userRoleList = new ArrayList<>();
        for (SysRole sysRole : roleList) {
            SysUserRole sysUserRole = new SysUserRole();
            sysUserRole.setId(IdUtil.getSnowflake(31, 31).nextIdStr());
            sysUserRole.setUserId(sysUser.getId());
            sysUserRole.setRoleId(sysRole.getId());
            userRoleList.add(sysUserRole);
        }
        userRoleService.remove(new QueryWrapper<SysUserRole>().eq(Constants.USER_ID, sysUser.getId()));
        userRoleService.saveBatch(userRoleList);
    }
}
